#include "WebSocketClient.h"
#include <iostream>

WebSocketClient::WebSocketClient(const std::string& address, int port)
    : address(address), port(port), context(nullptr), wsi(nullptr) {
    struct lws_context_creation_info context_info = {};
    struct lws_protocols protocols[] = {
        {"mrcore", WebSocketClient::callback, 0, 65536},
        {NULL, NULL, 0, 0} // terminator
    };

    context_info.port = CONTEXT_PORT_NO_LISTEN;
    context_info.protocols = protocols;

    context = lws_create_context(&context_info);
    if (!context) {
        std::cerr << "Failed to create context" << std::endl;
        throw std::runtime_error("Failed to create context");
    }

    struct lws_client_connect_info connect_info = {};
    connect_info.context = context;
    connect_info.address = address.c_str();
    connect_info.port = port;
    connect_info.path = "/";
    connect_info.host = lws_canonical_hostname(context);
    connect_info.origin = "origin";
    connect_info.protocol = protocols[0].name;

    wsi = lws_client_connect_via_info(&connect_info);
    if (!wsi) {
        std::cerr << "Failed to connect to server" << std::endl;
        lws_context_destroy(context);
        throw std::runtime_error("Failed to connect to server");
    }
}

WebSocketClient::~WebSocketClient() {
    if (context) {
        lws_context_destroy(context);
    }
}

void WebSocketClient::run() {
    while (lws_service(context, 1000) >= 0) {
        // Run the event loop
    }
}

int WebSocketClient::callback(struct lws *wsi, enum lws_callback_reasons reason,
                              void *user, void *in, size_t len) {
    switch (reason) {
        case LWS_CALLBACK_CLIENT_ESTABLISHED:
            std::cout << "Client connection established" << std::endl;
            break;
        case LWS_CALLBACK_CLIENT_RECEIVE:
            std::cout << "Received data: " << std::string((char *)in, len) << std::endl;
            break;
        case LWS_CALLBACK_CLIENT_CLOSED:
            std::cout << "Client connection closed" << std::endl;
            break;
        default:
            break;
    }
    return 0;
}